package utils

import (
	"encoding/base64"
	"strings"
)

type Base64 struct {
	encoder  string
	encoding *base64.Encoding
}

const encodeStd string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

var base64inst *Base64

func Base64Manager() *Base64 {
	if nil == base64inst {
		base64inst = &Base64{
			encoding: base64.StdEncoding,
			encoder:  encodeStd,
		}
	}
	return base64inst
}

func (a *Base64) SetEncoding(encoder string) error {
	if len(encoder) == 65 && encoder[64] == '=' {
		encoder = encoder[0:64]
	}

	if len(encoder) != 64 {
		return Error("encoder %s len (%v) is not 64", encoder, len(encoder))
	}

	for _, c := range encodeStd {
		if !strings.ContainsRune(encoder, c) {
			return Error("encoder %s char is not match", encoder)
		}
	}

	if encoder == a.encoder {
		Warning("repeat encoder : %s", encoder)
		return nil
	}

	a.encoding = base64.NewEncoding(encoder)
	a.encoder = encoder
	return nil
}

func (a *Base64) GetEncoder() string {
	return a.encoder
}

func (a *Base64) GenEncoding() string {
	var ret string
	var model = encodeStd

	for model != "" {
		idx := Rand(0, len(model))
		ret += model[idx : idx+1]
		model = model[0:idx] + model[idx+1:]
	}
	return ret
}

func (a *Base64) Encode(data string) string {
	encode := a.encoding.EncodeToString([]byte(data))
	return encode
}

func (a *Base64) Decode(data string) (string, error) {
	bdata, err := a.encoding.DecodeString(data)
	return string(bdata), err
}
